#include "NetModule.h"
#include "NetClientModule.h"
#include "Net.h"
#include "Depends/common/crc32.hpp"

FragrantGrass::NetClientModule::NetClientModule(IPluginManager* p)
{
    mBufferSize = 0;
    m_pPluginManager = p;
	mLastActionTime = GetPluginManager()->GetNowTime();
	mServerDataMap.clear();
	mServerTypeDataMap.clear();
	mTempNetList.clear();
	mSocketHandleMap.clear();
	m_pLogModule = NULL;
}

bool FragrantGrass::NetClientModule::Init()
{
	m_pLogModule = m_pPluginManager->FindModule<ILogModule>();

    for (int i = 0; i < FG_SERVER_TYPES::FG_ST_MAX; ++i)
    {
        INetClientModule::AddEventCallBack((FG_SERVER_TYPES) i, this, &NetClientModule::OnSocketEvent);
    }

    return true;
}

bool FragrantGrass::NetClientModule::AfterInit()
{
    return true;
}

bool FragrantGrass::NetClientModule::BeforeShut()
{
    return true;
}

bool FragrantGrass::NetClientModule::Shut()
{
    return true;
}

bool FragrantGrass::NetClientModule::Execute()
{
    ProcessExecute();
    ProcessAddNetConnect();

	if (mLastActionTime + 10 > GetPluginManager()->GetNowTime())
	{
		return true;
	}
	mLastActionTime = GetPluginManager()->GetNowTime();

	LogServerInfo();

    return true;
}

void FragrantGrass::NetClientModule::RemoveReceiveCallBack(const FG_SERVER_TYPES eType, const uint16_t nMsgID)
{
	SocketActionHandlerMap::iterator it = mSocketHandleMap.find((int)eType);
	if (it != mSocketHandleMap.end())
	{
		MSGID_HANDLER_MAP& msgHandlerMap = it->second->fixedMsgHandler;
		MSGID_HANDLER_MAP::iterator itHandler = msgHandlerMap.find(nMsgID);
		if (msgHandlerMap.end() == itHandler)
		{
			msgHandlerMap.erase(itHandler);
		}
	}
}

void FragrantGrass::NetClientModule::AddServer(const ConnectData& xInfo)
{
    mTempNetList.push_back(xInfo);
}

int FragrantGrass::NetClientModule::ExpandBufferSize(const unsigned int size)
{
    if (size > 0)
    {
        mBufferSize = size;
    }
    return mBufferSize;
}

int FragrantGrass::NetClientModule::AddReceiveCallBack(const FG_SERVER_TYPES eType, const uint16_t nMsgID,
	NET_MESSAGE_HANDLER_FUNCTOR_PTR functorPtr)
{
	FG_SHARE_PTR<SocketActionHandler>& socketActionHandlerPtr = mSocketHandleMap[eType];
	if (!socketActionHandlerPtr)
	{
		socketActionHandlerPtr = FG_SHARE_PTR<SocketActionHandler>(new SocketActionHandler());
	}

	std::list<NET_MESSAGE_HANDLER_FUNCTOR_PTR> xList;
	xList.push_back(functorPtr);

	socketActionHandlerPtr->fixedMsgHandler.insert(std::make_pair((int)nMsgID, xList));

    return 0;
}

int FragrantGrass::NetClientModule::AddReceiveCallBack(const FG_SERVER_TYPES eType, NET_MESSAGE_HANDLER_FUNCTOR_PTR functorPtr)
{
	FG_SHARE_PTR<SocketActionHandler>& socketActionHandlerPtr = mSocketHandleMap[eType];
	if (!socketActionHandlerPtr)
	{
		socketActionHandlerPtr = FG_SHARE_PTR<SocketActionHandler>(new SocketActionHandler());
	}
	socketActionHandlerPtr->msgHandlerList.push_back(functorPtr);
    return 0;
}


int FragrantGrass::NetClientModule::AddEventCallBack(const FG_SERVER_TYPES eType, NET_EVENT_HANDLER_FUNCTOR_PTR functorPtr)
{
	FG_SHARE_PTR<SocketActionHandler>& socketActionHandlerPtr = mSocketHandleMap[eType];
	if (!socketActionHandlerPtr)
	{
		socketActionHandlerPtr = FG_SHARE_PTR<SocketActionHandler>(new SocketActionHandler());
	}
	socketActionHandlerPtr->eventHandlerList.push_back(functorPtr);
    return 0;
}

void FragrantGrass::NetClientModule::SendByServerIDWithOutHead(const int nServerID, const uint16_t nMsgID, const std::string & strData)
{
	FG_SHARE_PTR<ConnectData> pServer(0);
	IDToServerDataMap::iterator it = mServerDataMap.find(nServerID);
	if (it != mServerDataMap.end())
	{
		pServer = it->second;
	}

	if (pServer)
	{
		FG_SHARE_PTR<INetModule> pNetModule = pServer->mxNetModule;
		if (pNetModule.get())
		{
			if (!pNetModule->send_msg_with_out_head(nMsgID, strData, 0))
			{
				std::ostringstream stream;
				stream << " SendMsgWithOutHead failed " << nServerID;
				stream << " msg id " << nMsgID;
				m_pLogModule->LogError(stream, __FUNCTION__, __LINE__);
			}
		}
	}
	else
	{
		std::ostringstream stream;
		stream << " can't find the server " << nServerID;
		stream << " msg id " << nMsgID;
		m_pLogModule->LogError(stream, __FUNCTION__, __LINE__);
	}
}

void FragrantGrass::NetClientModule::SendByServerID(const int nServerID, const uint16_t nMsgID, const std::string& strData)
{
	FG_SHARE_PTR<ConnectData> pServer(0);
	IDToServerDataMap::iterator it = mServerDataMap.find(nServerID);
	if (it != mServerDataMap.end())
	{
		pServer = it->second;
	}

	if (pServer)
	{
		FG_SHARE_PTR<INetModule> pNetModule = pServer->mxNetModule;
		if (pNetModule.get())
		{
			if (!pNetModule->send_msg_with_out_head(nMsgID, strData, 0))
			{
				std::ostringstream stream;
				stream << " SendMsgWithOutHead failed " << nServerID;
				stream << " msg id " << nMsgID;
				m_pLogModule->LogError(stream, __FUNCTION__, __LINE__);
			}
		}
	}
	else
	{
		std::ostringstream stream;
		stream << " can't find the server " << nServerID;
		stream << " msg id " << nMsgID;
		m_pLogModule->LogError(stream, __FUNCTION__, __LINE__);
	}
}

void FragrantGrass::NetClientModule::SendByServerID(const int nServerID, const uint16_t nMsgID, const std::string & strData, const GUID id)
{
	FG_SHARE_PTR<ConnectData> pServer(0);
	IDToServerDataMap::iterator it = mServerDataMap.find(nServerID);
	if (it != mServerDataMap.end())
	{
		pServer = it->second;
	}

	if (pServer)
	{
		FG_SHARE_PTR<INetModule> pNetModule = pServer->mxNetModule;
		if (pNetModule.get())
		{
			if (!pNetModule->send_msg_with_out_head(nMsgID, strData, 0, id))
			{
				std::ostringstream stream;
				stream << " SendMsgWithOutHead failed " << nServerID;
				stream << " msg id " << nMsgID;
				m_pLogModule->LogError(stream, __FUNCTION__, __LINE__);
			}
		}
	}
	else
	{
		std::ostringstream stream;
		stream << " can't find the server " << nServerID;
		stream << " msg id " << nMsgID;
		m_pLogModule->LogError(stream, __FUNCTION__, __LINE__);
	}
}

void FragrantGrass::NetClientModule::SendToAllServerWithOutHead(const uint16_t nMsgID, const std::string & strData)
{
	IDToServerDataMap::iterator it = mServerDataMap.begin();
	while (it != mServerDataMap.end())
	{
		FG_SHARE_PTR<ConnectData> pServer = it->second;
		if (!pServer)
		{
			continue;
		}

		FG_SHARE_PTR<INetModule> pNetModule = pServer->mxNetModule;
		if (pNetModule)
		{
			if (!pNetModule->send_msg_with_out_head(nMsgID, strData, 0))
			{
				std::ostringstream stream;
				stream << " SendMsgWithOutHead failed " << pServer->nGameID;
				stream << " msg id " << nMsgID;
				m_pLogModule->LogError(stream, __FUNCTION__, __LINE__);
			}
		}
		it++;
	}
}

void FragrantGrass::NetClientModule::SendToAllServer(const uint16_t nMsgID, const std::string& strData)
{
	IDToServerDataMap::iterator it = mServerDataMap.begin();
	while (it != mServerDataMap.end())
	{
		FG_SHARE_PTR<ConnectData> pServer = it->second;
		if (!pServer)
		{
			continue;
		}

		FG_SHARE_PTR<INetModule> pNetModule = pServer->mxNetModule;
		if (pNetModule)
		{
			if (!pNetModule->send_msg_with_out_head(nMsgID, strData, 0))
			{
				std::ostringstream stream;
				stream << " SendMsgWithOutHead failed " << pServer->nGameID;
				stream << " msg id " << nMsgID;
				m_pLogModule->LogError(stream, __FUNCTION__, __LINE__);
			}
		}
		it++;
	}
}

void FragrantGrass::NetClientModule::SendToAllServer(const uint16_t nMsgID, const std::string & strData, const GUID id)
{
	IDToServerDataMap::iterator it = mServerDataMap.begin();
	while (it != mServerDataMap.end())
	{
		FG_SHARE_PTR<ConnectData> pServer = it->second;
		if (pServer && pServer->mxNetModule)
		{
			if (!pServer->mxNetModule->send_msg_with_out_head(nMsgID, strData, 0, id))
			{
				std::ostringstream stream;
				stream << " send_msg_with_out_head failed " << pServer->nGameID;
				stream << " msg id " << nMsgID;
				m_pLogModule->LogError(stream, __FUNCTION__, __LINE__);
			}
		}
		++it;
	}
}

void FragrantGrass::NetClientModule::SendToAllServerWithOutHead(const FG_SERVER_TYPES eType, const uint16_t nMsgID, const std::string & strData)
{
	IDToServerDataMap::iterator it = mServerDataMap.begin();
	while (it != mServerDataMap.end())
	{
		FG_SHARE_PTR<ConnectData> pServer = it->second;
		if (!pServer)
		{
			continue;
		}

		FG_SHARE_PTR<INetModule> pNetModule = pServer->mxNetModule;
		if (pNetModule && eType == pServer->eServerType)
		{
			if (!pNetModule->send_msg_with_out_head(nMsgID, strData, 0))
			{
				std::ostringstream stream;
				stream << " SendMsgWithOutHead failed " << pServer->nGameID;
				stream << " msg id " << nMsgID;
				m_pLogModule->LogError(stream, __FUNCTION__, __LINE__);
			}
		}
		it++;
	}
}

void FragrantGrass::NetClientModule::SendToAllServer(const FG_SERVER_TYPES eType, const uint16_t nMsgID, const std::string& strData)
{
	IDToServerDataMap::iterator it = mServerDataMap.begin();
	while (it != mServerDataMap.end())
	{
		FG_SHARE_PTR<ConnectData> pServer = it->second;
		if (!pServer)
		{
			continue;
		}

        FG_SHARE_PTR<INetModule> pNetModule = pServer->mxNetModule;
        if (pNetModule && eType == pServer->eServerType)
        {
			if (!pNetModule->send_msg_with_out_head(nMsgID, strData, 0))
			{
				std::ostringstream stream;
				stream << " SendMsgWithOutHead failed " << pServer->nGameID;
				stream << " msg id " << nMsgID;
				m_pLogModule->LogError(stream, __FUNCTION__, __LINE__);
			}
        }

		it++;
    }
}

void FragrantGrass::NetClientModule::SendToAllServer(const FG_SERVER_TYPES eType, const uint16_t nMsgID, const std::string & strData, const GUID id)
{
	IDToServerDataMap::iterator it = mServerDataMap.begin();
	while (it != mServerDataMap.end())
	{
		FG_SHARE_PTR<ConnectData> pServer = it->second;
		if (pServer && pServer->mxNetModule)
		{
			if (!pServer->mxNetModule->send_msg_with_out_head(nMsgID, strData, 0, id))
			{
				std::ostringstream stream;
				stream << " send_msg_with_out_head failed " << pServer->nGameID;
				stream << " msg id " << nMsgID;
				m_pLogModule->LogError(stream, __FUNCTION__, __LINE__);
			}
		}
		++it;
	}
}

void FragrantGrass::NetClientModule::SendToServerByPB(const int nServerID, const uint16_t nMsgID, const google::protobuf::Message& xData)
{
	IDToServerDataMap::iterator it = mServerDataMap.begin();
	if (it != mServerDataMap.end() && it->second && it->second->mxNetModule)
	{
		FG_SHARE_PTR<ConnectData> pServer = it->second;
		if (!pServer->mxNetModule->send_protobuf_message(nMsgID, xData, 0))
		{
			std::ostringstream stream;
			stream << " SendMsgPB failed " << pServer->nGameID;
			stream << " msg id " << nMsgID;
			m_pLogModule->LogError(stream, __FUNCTION__, __LINE__);
		}
	}
	else
	{
		std::ostringstream stream;
		stream << " can't find the server " << nServerID;
		stream << " msg id " << nMsgID;
		m_pLogModule->LogError(stream, __FUNCTION__, __LINE__);
	}
}

void FragrantGrass::NetClientModule::SendToServerByPB(const int nServerID, const uint16_t nMsgID, const google::protobuf::Message & xData, const GUID id)
{
	IDToServerDataMap::iterator it = mServerDataMap.begin();
	if (it != mServerDataMap.end() && it->second && it->second->mxNetModule)
	{
		FG_SHARE_PTR<ConnectData> pServer = it->second;
		if (!pServer->mxNetModule->send_protobuf_message(nMsgID, xData, 0, id))
		{
			std::ostringstream stream;
			stream << " SendMsgPB failed " << pServer->nGameID;
			stream << " msg id " << nMsgID;
			m_pLogModule->LogError(stream, __FUNCTION__, __LINE__);
		}
	}
	else
	{
		std::ostringstream stream;
		stream << " can't find the server " << nServerID;
		stream << " msg id " << nMsgID;
		m_pLogModule->LogError(stream, __FUNCTION__, __LINE__);
	}
}

void FragrantGrass::NetClientModule::SendToAllServerByPB(const uint16_t nMsgID, const google::protobuf::Message& xData)
{
	IDToServerDataMap::iterator it = mServerDataMap.begin();
	while (it != mServerDataMap.end())
	{
		FG_SHARE_PTR<ConnectData> pServer = it->second;
		if (pServer && pServer->mxNetModule)
		{
			if (!pServer->mxNetModule->send_protobuf_message(nMsgID, xData, 0))
			{
				std::ostringstream stream;
				stream << " SendMsgPB failed " << pServer->nGameID;
				stream << " msg id " << nMsgID;
				m_pLogModule->LogError(stream, __FUNCTION__, __LINE__);
			}
		}
		++it;
	}
}

void FragrantGrass::NetClientModule::SendToAllServerByPB(const FG_SERVER_TYPES eType, const uint16_t nMsgID,
                                             const google::protobuf::Message& xData)
{
	IDToServerDataMap::iterator it = mServerDataMap.begin();
	while (it != mServerDataMap.end())
	{
		FG_SHARE_PTR<ConnectData> pServer = it->second;
		if (pServer && pServer->mxNetModule && pServer->eServerType == eType && pServer->eState == ConnectDataState::NORMAL)
		{
			if (!pServer->mxNetModule->send_protobuf_message(nMsgID, xData, 0))
			{
				std::ostringstream stream;
				stream << " SendMsgPB failed " << pServer->nGameID;
				stream << " msg id " << nMsgID;
				m_pLogModule->LogError(stream, __FUNCTION__, __LINE__);
			}
		}
		++it;
	}
}

void FragrantGrass::NetClientModule::SendBySuitWithOutHead(const FG_SERVER_TYPES eType, const std::string & strHashKey, const uint16_t nMsgID, const std::string & strData)
{
	uint32_t nCRC32 = FragrantGrass::CRC32(strHashKey);
	SendBySuitWithOutHead(eType, nCRC32, nMsgID, strData);
}

void FragrantGrass::NetClientModule::SendBySuit(const FG_SERVER_TYPES eType, const std::string& strHashKey, const uint16_t nMsgID,
                                    const std::string& strData)
{
    uint32_t nCRC32 = FragrantGrass::CRC32(strHashKey);
    SendBySuit(eType, nCRC32, nMsgID, strData);
}

void FragrantGrass::NetClientModule::SendBySuit(const FG_SERVER_TYPES eType, const std::string & strHashKey, const uint16_t nMsgID, const std::string & strData, const GUID id)
{
	uint32_t nCRC32 = FragrantGrass::CRC32(strHashKey);
	SendBySuit(eType, nCRC32, nMsgID, strData, id);
}

void FragrantGrass::NetClientModule::SendBySuitWithOutHead(const FG_SERVER_TYPES eType, const int nHashKey32, const uint16_t nMsgID, const std::string & strData)
{
	TypeIdServerDataMap::iterator it = mServerTypeDataMap.find(eType);
	if (it != mServerTypeDataMap.end())
	{
		FG_SHARE_PTR<ConnectData> pConnectData(0);
		IDToServerDataMap& xConnectDataMap = it->second;
		IDToServerDataMap::iterator itConnect = xConnectDataMap.find(nHashKey32);
		if (itConnect != xConnectDataMap.end())
		{
			pConnectData = itConnect->second;
			SendByServerIDWithOutHead(pConnectData->nGameID, nMsgID, strData);
		}
	}
	else
	{
		std::ostringstream stream;
		stream << " can't find the server type " << eType;
		stream << " msg id " << nMsgID;
		m_pLogModule->LogError(stream, __FUNCTION__, __LINE__);
	}
}

void FragrantGrass::NetClientModule::SendBySuit(const FG_SERVER_TYPES eType, const int nHashKey, const uint16_t nMsgID, const std::string& strData)
{
	TypeIdServerDataMap::iterator it = mServerTypeDataMap.find(eType);
	if (it != mServerTypeDataMap.end())
	{
		FG_SHARE_PTR<ConnectData> pConnectData(0);
		IDToServerDataMap& xConnectDataMap = it->second;
		IDToServerDataMap::iterator itConnect = xConnectDataMap.find(nHashKey);
		if (itConnect != xConnectDataMap.end())
		{
			pConnectData = itConnect->second;
		}
		if (pConnectData)
		{
			SendByServerID(pConnectData->nGameID, nMsgID, strData);
		}
	}
	else
	{
		std::ostringstream stream;
		stream << " can't find the server type " << eType;
		stream << " msg id " << nMsgID;
		m_pLogModule->LogError(stream, __FUNCTION__, __LINE__);
	}
}

void FragrantGrass::NetClientModule::SendBySuit(const FG_SERVER_TYPES eType, const int nHashKey32, const uint16_t nMsgID, const std::string & strData, const GUID id)
{
	TypeIdServerDataMap::iterator it = mServerTypeDataMap.find(eType);
	if (it != mServerTypeDataMap.end())
	{
		FG_SHARE_PTR<ConnectData> pConnectData(0);
		IDToServerDataMap& xConnectDataMap = it->second;
		IDToServerDataMap::iterator itConnect = xConnectDataMap.find(nHashKey32);
		if (itConnect != xConnectDataMap.end())
		{
			pConnectData = itConnect->second;
		}
		if (pConnectData)
		{
			SendByServerID(pConnectData->nGameID, nMsgID, strData, id);
		}
	}
	else
	{
		std::ostringstream stream;
		stream << " can't find the server type " << eType;
		stream << " msg id " << nMsgID;
		m_pLogModule->LogError(stream, __FUNCTION__, __LINE__);
	}
}

void FragrantGrass::NetClientModule::SendSuitByPB(const FG_SERVER_TYPES eType, const std::string& strHashKey, const uint16_t nMsgID, const google::protobuf::Message& xData)
{
    uint32_t nCRC32 = FragrantGrass::CRC32(strHashKey);
    SendSuitByPB(eType, nCRC32, nMsgID, xData);
}

void FragrantGrass::NetClientModule::SendSuitByPB(const FG_SERVER_TYPES eType, const std::string & strHashKey, const uint16_t nMsgID, const google::protobuf::Message & xData, const GUID id)
{
	uint32_t nCRC32 = FragrantGrass::CRC32(strHashKey);
	SendSuitByPB(eType, nCRC32, nMsgID, xData, id);
}

void FragrantGrass::NetClientModule::SendSuitByPB(const FG_SERVER_TYPES eType, const int nHashKey, const uint16_t nMsgID, const google::protobuf::Message& xData)
{
	TypeIdServerDataMap::iterator it = mServerTypeDataMap.find(eType);
	if (it != mServerTypeDataMap.end())
	{
		FG_SHARE_PTR<ConnectData> pConnectData(0);
		IDToServerDataMap& xConnectDataMap = it->second;
		IDToServerDataMap::iterator itConnect = xConnectDataMap.find(nHashKey);
		if (itConnect != xConnectDataMap.end())
		{
			pConnectData = itConnect->second;
		}
		if (pConnectData)
		{
			SendToServerByPB(pConnectData->nGameID, nMsgID, xData);
		}
	}
}

void FragrantGrass::NetClientModule::SendSuitByPB(const FG_SERVER_TYPES eType, const int nHashKey32, const uint16_t nMsgID, const google::protobuf::Message & xData, const GUID id)
{
	TypeIdServerDataMap::iterator it = mServerTypeDataMap.find(eType);
	if (it != mServerTypeDataMap.end())
	{
		FG_SHARE_PTR<ConnectData> pConnectData(0);
		IDToServerDataMap& xConnectDataMap = it->second;
		IDToServerDataMap::iterator itConnect = xConnectDataMap.find(nHashKey32);
		if (itConnect != xConnectDataMap.end())
		{
			pConnectData = itConnect->second;
		}
		if (pConnectData)
		{
			SendToServerByPB(pConnectData->nGameID, nMsgID, xData, id);
		}
	}
}

FG_SHARE_PTR<FragrantGrass::ConnectData> FragrantGrass::NetClientModule::GetServerNetInfo(const FG_SERVER_TYPES eType)
{
	TypeIdServerDataMap::iterator it = mServerTypeDataMap.find(eType);
	if (it == mServerTypeDataMap.end())
	{
		return FG_SHARE_PTR<FragrantGrass::ConnectData>(NULL);
	}

	IDToServerDataMap::iterator connect_it = it->second.begin();
	while (connect_it != it->second.end())
	{
		if (connect_it->second)
			return connect_it->second;
		connect_it++;
	}

	return FG_SHARE_PTR<FragrantGrass::ConnectData>(NULL);
}

FG_SHARE_PTR<FragrantGrass::ConnectData> FragrantGrass::NetClientModule::GetServerNetInfo(const int nServerID)
{
	IDToServerDataMap::iterator it = mServerDataMap.find(nServerID);
	if (it != mServerDataMap.end())
		return it->second;

	return FG_SHARE_PTR<ConnectData>(NULL);
}

std::map<int, FG_SHARE_PTR<FragrantGrass::ConnectData>>& FragrantGrass::NetClientModule::GetServerList()
{
    return mServerDataMap;
}

FG_SHARE_PTR<FragrantGrass::ConnectData> FragrantGrass::NetClientModule::GetServerNetInfo(const INet* pNet)
{
	IDToServerDataMap::iterator it = mServerDataMap.begin();
	while (it != mServerDataMap.end())
	{
		if (it->second && it->second->mxNetModule && pNet == it->second->mxNetModule->getNet())
		{
			return it->second;
		}
		++it;
	}
    return FG_SHARE_PTR<ConnectData>(NULL);
}

void FragrantGrass::NetClientModule::InitNetHandlers(FG_SHARE_PTR<ConnectData> pServerData)
{
	std::ostringstream stream;
	stream << "AddServer Type: " << pServerData->eServerType << " Server ID: " << pServerData->nGameID << " State: "
		<< pServerData->eState << " IP: " << pServerData->strIP << " Port: " << pServerData->nPort;

	m_pLogModule->LogInfo(stream.str());

	int key = (int)pServerData->eServerType;
	SocketActionHandlerMap::iterator it = mSocketHandleMap.find(key);
	auto& socketActionHandler = mSocketHandleMap[key];
	if (!socketActionHandler)
	{
		socketActionHandler = FG_SHARE_PTR<SocketActionHandler>(new SocketActionHandler());
	}

    //add msg handler
	if (true)
	{
		MSGID_HANDLER_MAP& fixedMsgHandleMap = socketActionHandler->fixedMsgHandler;
		for (MSGID_HANDLER_MAP::iterator it = fixedMsgHandleMap.begin(); it != fixedMsgHandleMap.end(); ++it)
		{
			MESSAGE_HANDLER_LIST& xMsgHandlers = it->second;
			for (MESSAGE_HANDLER_LIST::iterator itHandlers = xMsgHandlers.begin(); itHandlers != xMsgHandlers.end(); ++itHandlers)
			{
				pServerData->mxNetModule->register_net_message_handler(it->first, *itHandlers);
			}
		}
	}

    //register event handler
	if (true)
	{
		EVENT_HANDLER_LIST& eventHandlerList = socketActionHandler->eventHandlerList;
		for (EVENT_HANDLER_LIST::iterator it = eventHandlerList.begin(); it != eventHandlerList.end(); ++it)
		{
			pServerData->mxNetModule->register_net_event_handler(*it);
		}
	}

	//register global msg handler
	if (true)
	{
		MESSAGE_HANDLER_LIST& msgHandlerList = socketActionHandler->msgHandlerList;
		for (MESSAGE_HANDLER_LIST::iterator it = msgHandlerList.begin(); it != msgHandlerList.end(); ++it)
		{
			pServerData->mxNetModule->register_net_message_handler(*it);
		}
	}
}

void FragrantGrass::NetClientModule::ProcessExecute()
{
	for (IDToServerDataMap::iterator it = mServerDataMap.begin();it != mServerDataMap.end();++it)
	{
		FG_SHARE_PTR<ConnectData> pServerData = it->second;
		if (pServerData)
		{
			switch (pServerData->eState)
			{
			case ConnectDataState::DISCONNECT:
			{
				if (NULL != pServerData->mxNetModule)
				{
					pServerData->mxNetModule = NULL;
					pServerData->eState = ConnectDataState::RECONNECT;
				}
			}
			break;
			case ConnectDataState::CONNECTING:
			{
				if (pServerData->mxNetModule)
				{
					pServerData->mxNetModule->Execute();
				}
			}
			break;
			case ConnectDataState::NORMAL:
			{
				if (pServerData->mxNetModule)
				{
					pServerData->mxNetModule->Execute();

					KeepState(pServerData);
				}
			}
			break;
			case ConnectDataState::RECONNECT:
			{
				if ((pServerData->mLastActionTime + 10) >= GetPluginManager()->GetNowTime())
				{
					break;
				}

				if (NULL != pServerData->mxNetModule)
				{
					pServerData->mxNetModule = NULL;
				}

				pServerData->eState = ConnectDataState::CONNECTING;
				pServerData->mxNetModule = FG_SHARE_PTR<INetModule>(new NetModule(m_pPluginManager));

				pServerData->mxNetModule->Awake();
				pServerData->mxNetModule->Init();
				pServerData->mxNetModule->AfterInit();
				pServerData->mxNetModule->ReadyExecute();

				pServerData->mxNetModule->init_as_client(pServerData->strIP.c_str(), pServerData->nPort);

				InitNetHandlers(pServerData);
			}
			break;
			default:
				break;
			}
		}
	}
}

void FragrantGrass::NetClientModule::LogServerInfo()
{
	if (NULL != m_pLogModule && mServerDataMap.size() > 0)
	{
		m_pLogModule->LogInfo("This is a client, begin to print Server Info-------------------");

		for (IDToServerDataMap::iterator it = mServerDataMap.begin(); it != mServerDataMap.end(); ++it)
		{
			FG_SHARE_PTR<ConnectData>& pServerData = it->second;
			if (pServerData)
			{
				std::ostringstream stream;
				stream << "Type: " << pServerData->eServerType << " Server ID: " << pServerData->nGameID << " State: "
					<< pServerData->eState << " IP: " << pServerData->strIP << " Port: " << pServerData->nPort;

				if (pServerData->eState == ConnectDataState::NORMAL)
				{
					m_pLogModule->LogInfo(stream.str());
				}
				else
				{
					m_pLogModule->LogError(stream.str());
				}
			}
		}

		m_pLogModule->LogInfo("This is a client, end to print Server Info---------------------");
	}
}

void FragrantGrass::NetClientModule::KeepState(FG_SHARE_PTR<ConnectData> pServerData)
{
    if (pServerData->mLastActionTime + 10 > GetPluginManager()->GetNowTime())
    {
        return;
    }

    pServerData->mLastActionTime = GetPluginManager()->GetNowTime();

	//send message
}

void FragrantGrass::NetClientModule::OnSocketEvent(const SOCK fd, const FG_NET_EVENT eEvent, INet* pNet)
{
    if (eEvent & FG_NET_EVENT::FG_NET_EVENT_CONNECTED)
    {
        OnConnected(fd, pNet);
    }
	else
    {
        OnDisConnected(fd, pNet);
    }
}

int FragrantGrass::NetClientModule::OnConnected(const SOCK fd, INet* pNet)
{
    FG_SHARE_PTR<ConnectData> pServerInfo = GetServerNetInfo(pNet);
    if (pServerInfo)
    {
        pServerInfo->eState = ConnectDataState::NORMAL;

        //for type--suit
		TypeIdServerDataMap::iterator it = mServerTypeDataMap.find(pServerInfo->eServerType);
		IDToServerDataMap& xConnectDataMap = mServerTypeDataMap[pServerInfo->eServerType];

		xConnectDataMap[pServerInfo->nGameID] = pServerInfo;
    }

    return 0;
}

int FragrantGrass::NetClientModule::OnDisConnected(const SOCK fd, INet* pNet)
{
    FG_SHARE_PTR<ConnectData> pServerInfo = GetServerNetInfo(pNet);
    if (NULL != pServerInfo)
    {
        pServerInfo->eState = ConnectDataState::DISCONNECT;
        pServerInfo->mLastActionTime = GetPluginManager()->GetNowTime();

        //for type--suit
		TypeIdServerDataMap::iterator it = mServerTypeDataMap.find(pServerInfo->eServerType);
		if (it != mServerTypeDataMap.end())
		{
			IDToServerDataMap& xConnectDataMap = it->second;
			xConnectDataMap.erase(pServerInfo->nGameID);
		}
    }

    return 0;
}

void FragrantGrass::NetClientModule::ProcessAddNetConnect()
{
    for (std::list<ConnectData>::iterator it = mTempNetList.begin(); it != mTempNetList.end(); ++it)
    {
        const ConnectData& xInfo = *it;
		FG_SHARE_PTR<ConnectData> xServerData(0);
		IDToServerDataMap::iterator itData = mServerDataMap.find(xInfo.nGameID);
		if (itData != mServerDataMap.end())
		{
			xServerData = itData->second;
		}

        if (!xServerData)
        {
            xServerData = FG_SHARE_PTR<ConnectData>(new ConnectData());

            xServerData->nGameID = xInfo.nGameID;
            xServerData->eServerType = xInfo.eServerType;
            xServerData->strIP = xInfo.strIP;
            xServerData->strName = xInfo.strName;
            xServerData->eState = ConnectDataState::CONNECTING;
            xServerData->nPort = xInfo.nPort;
            xServerData->mLastActionTime = GetPluginManager()->GetNowTime();

            xServerData->mxNetModule = FG_SHARE_PTR<INetModule>(new NetModule(m_pPluginManager));

			xServerData->mxNetModule->Awake();
			xServerData->mxNetModule->Init();
			xServerData->mxNetModule->AfterInit();
			xServerData->mxNetModule->ReadyExecute();

            xServerData->mxNetModule->init_as_client(xServerData->strIP.c_str(), xServerData->nPort);
            xServerData->mxNetModule->expand_buffer_size(mBufferSize);

            InitNetHandlers(xServerData);

			mServerDataMap[xInfo.nGameID] = xServerData;
        }
		else
		{
			xServerData->nWorkLoad = xInfo.nWorkLoad;
		}
    }

    mTempNetList.clear();
}